#pragma once
#include<unordered_map>
#include<pthread.h>
#include"util.hpp"
#include"config.hpp"
 namespace cloud{

   struct BackupInfo{

        bool _packflag;//是否压缩标志位
        size_t _fsize;//文件大小
        time_t _mtime;//最后一次修改时间
        time_t _atime;//最后一次访问时间
        std::string _realpath;//实际存储路径
        std::string _packpath;//文件压缩路径
        std::string _url;
        void NewBackupInfo(const std::string&realpath)
        {   
            
            FileUtil fu(realpath);
            if(fu.Exists()==false)
            {  
                std::cout<<"newBackupInfo :file not exists\n ";
                return ;
            }
            Config* config=Config::GetInstance();
            std::string packdir=config->GetPackDir();
            std::string packsuffix=config->GetPackFileSuffix();
            std::string downloadprefix=config->GetDownloadPrefix();

            this->_packflag=false;
            this->_fsize=fu.FileSize();
            this->_mtime=fu.LastMTime();
            this->_atime=fu.LastATime();
            this->_realpath=realpath;
            this->_packpath=packdir+fu.FileName()+packsuffix;
            this->_url=downloadprefix+fu.FileName();
            return ;

        }

    };

    class DataManger{

        
        public:
        DataManger(){
            _backup_file=Config::GetInstance()->GetBackupFile();
            pthread_rwlock_init(&_rwlock,nullptr);
            InitLoad();

        }
        ~DataManger()
        {
            pthread_rwlock_destroy(&_rwlock);
        }

        bool Insert(const BackupInfo&info){
             pthread_rwlock_wrlock(&_rwlock);
             _table[info._url]=info;
             pthread_rwlock_unlock(&_rwlock);
             Storage();
             return true;
        }

        bool Update(const BackupInfo&info){
            pthread_rwlock_wrlock(&_rwlock);
             _table[info._url]=info;
             pthread_rwlock_unlock(&_rwlock);
             Storage();
            return true;
        }
        bool GetOneByURL(const std::string &url,BackupInfo*info){
            pthread_rwlock_wrlock(&_rwlock);
            //url 是key值直接进行查找
            auto it=_table.find(url);
            if(it==_table.end())
            {  
              pthread_rwlock_unlock(&_rwlock);
                return false;
            }
            *info=it->second;
            pthread_rwlock_unlock(&_rwlock);
            return true;
        }
        bool GetOneByRealPath(const std::string &realpath,BackupInfo*info){
            pthread_rwlock_wrlock(&_rwlock);
            auto it=_table.begin();
            for(;it!=_table.end();++it)
            {
               if(it->second._realpath==realpath)
               {
                 *info=it->second;
                 pthread_rwlock_unlock(&_rwlock);
                 return true;
               }
            }
            pthread_rwlock_unlock(&_rwlock);
            return false;

        }
        bool GetAll(std::vector<BackupInfo>*arry)
        {
            pthread_rwlock_wrlock(&_rwlock);
             auto it=_table.begin();
            for(;it!=_table.end();++it)
            {
               arry->push_back(it->second);
            }
            
            pthread_rwlock_unlock(&_rwlock);
            return true;

        }

        bool Storage()
        {
            //1.获取所有数据
            std::vector<BackupInfo>arry;
            this->GetAll(&arry);
            //2.添加到Json ::value
            Json::Value root;
            for(int i=0;i<arry.size();i++)
            {   
                Json::Value item;
                item["pack_flag"] = arry[i]._packflag;
                item["fsize"] = (Json::Value::Int64)arry[i]._fsize;
                item["atime"] = (Json::Value::Int64)arry[i]._atime;
                item["mtime"] = (Json::Value::Int64)arry[i]._mtime;
                item["real_path"] = arry[i]._realpath;
                item["pack_path"] = arry[i]._packpath;
                item["url"] = arry[i]._url;
                root.append(item);
            }
          
            //3.对json::value 序列化
            std::string body;
            JsonUtil::Serialize(root,&body);
            //4.写文件
            FileUtil fu(_backup_file);
            fu.SetContent(body);
             return true;
        }

        bool InitLoad()
        {
            //1.将数据文件中的数据读取出来
             FileUtil fu(_backup_file);
             if(fu.Exists()==false)
             {  
                std::cout<<" Data InitLoag fiaied! file not exists\n";
                return true;
             }
             std::string body;
             fu.GetContent(body);
             //2.反序列化
             Json::Value root;
             JsonUtil::UnSerialize(body,&root);
             //3.将序列化得到的Json::value中的数据添加到table中
            for(int i=0;i<root.size();i++)
            {
                BackupInfo info;
                info._packflag=root[i]["pack_flag"].asBool();
                info._fsize=root[i]["fsize"].asInt64();
                info._atime=root[i]["atime"].asInt64();
                info._mtime=root[i]["mtime"].asInt64();
                info._packpath=root[i]["pack_path"].asString();
                info._realpath=root[i]["real_path"].asString();
                info._url=root[i]["url"].asString();
                Insert(info);

            }
            return true;


        }
        private:
        std::string _backup_file;
        pthread_rwlock_t _rwlock;//读写锁保护
        std::unordered_map<std::string,BackupInfo>_table;
    };


 }


